package cn.xiuxius.embedded.toolwindow.projecttool;

import cn.xiuxius.embedded.toolwindow.model.*;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.impl.ConsoleViewImpl;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandlerFactory;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.Key;
import com.intellij.ui.OnePixelSplitter;
import com.intellij.util.ui.JBUI;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.*;
import java.util.List;
import java.util.regex.Pattern;

@Slf4j
public class ProjectToolWindow extends SimpleToolWindowPanel {

    private Project project;

    private LogPanel logPanel;

    private final List<ProjectCommandItem> mainOptionItems = new ArrayList<>();

    public ProjectToolWindow(Project project) {
        super(true, true);
        this.project = project;
        initItems();
        JPanel mainArea = createMainArea();
        JComponent logArea = createLogArea();

        // 使用OnePixelSplitter做上下结构，上面按钮区域固定高度
        OnePixelSplitter mainSplitter = new OnePixelSplitter(true, 0.30f);
        mainSplitter.setFirstComponent(mainArea);
        mainSplitter.setSecondComponent(logArea);
        mainSplitter.setDividerPositionStrategy(Splitter.DividerPositionStrategy.KEEP_FIRST_SIZE);

        add(mainSplitter, BorderLayout.CENTER);
    }

    private void initItems() {
        initMainOptionItem();
    }

    private void startConvert(ProjectCommandItem projectCommandItem) {
        String home = System.getenv("EASY_STC_HOME");
        if (home == null || home.isEmpty()) {
            Messages.showErrorDialog(this, "未设置 EASY_STC_HOME 环境变量", "错误");
            return;
        }
        File exe = new File(home, "easystc.exe");
        if (!exe.exists()) {
            Messages.showErrorDialog(this, "easystc.exe 不存在: " + exe.getAbsolutePath(), "错误");
            return;
        }

        try {
            GeneralCommandLine commandLine = new GeneralCommandLine();
            commandLine.setExePath(exe.getAbsolutePath());
            commandLine.addParameters("process");
            if (!projectCommandItem.getOption().isDefault()) {
                if ("ToRTX51".equalsIgnoreCase(projectCommandItem.getOption().getCmdValue())) {
                    commandLine.addParameter("-p");
                }
            }
            commandLine.setWorkDirectory(project.getBasePath());
            OSProcessHandler handler = ProcessHandlerFactory.getInstance().createColoredProcessHandler(commandLine);
            handler.addProcessListener(new ProcessAdapter() {
                private static final Pattern ANSI_PATTERN = Pattern.compile("\u001B\\[[;\\d]*m");
                @Override
                public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
                    logPanel.appendLog(event.getText());
                }
            });
            handler.startNotify();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }



    public void initMainOptionItem() {
        mainOptionItems.addAll(List.of(
                new ProjectCommandItem(OptionUIType.COMBO_BOX_WITH_RUN, "project-context-convert", "RTX51-EasySTC代码内容转换",
                        new StringCommandOption("preprocess", "FromRTX51", false)
                                .options(() -> List.of("FromRTX51", "ToRTX51"))
                        , false
                        , this::startConvert)
        ));
    }

    /**
     * 按钮操作区域，使用 BoxLayout 垂直排列，行高固定，间距小，控件紧凑
     */
    private JPanel createMainArea() {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.setBorder(JBUI.Borders.empty(10));
        panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 160));
        panel.setMinimumSize(new Dimension(100, 100));

        for (ProjectCommandItem item : mainOptionItems) {
            JPanel rowPanel = new JPanel();
            rowPanel.setLayout(new BoxLayout(rowPanel, BoxLayout.Y_AXIS));
            rowPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
            rowPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 70)); // 高度稍微放开

            if (item.getType() == OptionUIType.COMBO_BOX_WITH_RUN) {
                JLabel label = new JLabel(item.getDisplayName(), SwingConstants.CENTER);
                label.setAlignmentX(Component.CENTER_ALIGNMENT);
                label.setFont(label.getFont().deriveFont(Font.BOLD, 14f));
                label.setBorder(JBUI.Borders.emptyBottom(5));

                JPanel controlsPanel = new JPanel(new BorderLayout(5, 0));
                JComboBox<Selectable> comboBox = new ComboBox<>(
                        item.getOption().getSelectables().toArray(new Selectable[0]));
                comboBox.setPreferredSize(new Dimension(180, 30));

                if (item.getOption().getDefaultValue() != null) {
                    for (Selectable selectable : item.getOption().getSelectables()) {
                        if (selectable.getValue().equals(item.getOption().getDefaultValue())) {
                            comboBox.setSelectedItem(selectable);
                            item.getOption().setCmdValue(selectable.getValue());
                            break;
                        }
                    }
                }

                JButton button = new JButton("运行");
                button.setPreferredSize(new Dimension(80, 30));
                button.putClientProperty("JButton.buttonType", "roundRect");
                button.addActionListener(e -> {
                    Selectable selectedItem = (Selectable) comboBox.getSelectedItem();
                    if (selectedItem != null) {
                        item.getOption().setCmdValue(selectedItem.getValue());
                    }
                    if (item.getOnClick() != null) item.getOnClick().accept(item);
                });

                controlsPanel.add(comboBox, BorderLayout.CENTER);
                controlsPanel.add(button, BorderLayout.EAST);

                rowPanel.add(label);
                rowPanel.add(controlsPanel);
            }

            panel.add(rowPanel);
            panel.add(Box.createVerticalStrut(10)); // 间距
        }

        return panel;
    }

    /**
     * 日志输出区域，带标题栏和清空按钮，支持Ctrl+滚轮字体缩放，带边框
     */
    private JComponent createLogArea() {
        logPanel = new LogPanel(project);
        return logPanel;
    }

    public static class LogPanel extends JPanel {

        private final ConsoleView consoleView;

        public LogPanel(Project project) {
            super(new BorderLayout());

            consoleView = new ConsoleViewImpl(project, false);
            JComponent consoleComponent = consoleView.getComponent();

            // 顶部操作栏
            JPanel headerPanel = new JPanel(new BorderLayout());
            JLabel title = new JLabel("日志输出");
            title.setFont(title.getFont().deriveFont(Font.BOLD));
            JButton clearButton = new JButton("清空");
            clearButton.setMargin(JBUI.insets(2, 8));
            clearButton.addActionListener(e -> consoleView.clear());

            JPanel right = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
            right.setOpaque(false);
            right.add(clearButton);

            headerPanel.add(title, BorderLayout.WEST);
            headerPanel.add(right, BorderLayout.EAST);

            add(headerPanel, BorderLayout.NORTH);
            add(consoleComponent, BorderLayout.CENTER);
        }

        private void appendColoredLog(String message) {
            if (message.contains("ERROR")) {
                consoleView.print(message , ConsoleViewContentType.ERROR_OUTPUT);
            } else if (message.contains("WARN")) {
                consoleView.print(message, ConsoleViewContentType.LOG_WARNING_OUTPUT);
            } else {
                consoleView.print(message, ConsoleViewContentType.LOG_INFO_OUTPUT);
            }
        }

        public void appendLog(String message) {
            appendColoredLog(message);
        }
    }

}
